﻿//
// Author: rgy
// Date: 2016-06-13 19:56:00
//

using UnityEngine;
using System.Collections.Generic;
using SLua;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

/// <summary>
/// 纯自动适配无限循环滚动
/// </summary>
[RequireComponent(typeof(RectTransform))]
public class SoarDAutoScroll : CanvasModeBehaviour, ISoarDScroll, IPointerDownHandler, IPointerUpHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, ICanvasElement
{
    public enum ReleasePosition
    {
        None,
        Down,
        Top,
    }
    
    public enum ReleaseEndShow
    {
        Hide,
        ShowEndHint,
    }

    public bool m_Horizontal;                                       //水平移动
    public bool m_Vertical;                                         //垂直移动
    public RectTransform m_Viewport;                                //显示
    public RectTransform m_Content;                                 //内容
    private float m_clampedLength = 0;                                   //夹的距离
    public RectTransform m_HeadPanel;                               //头部跟随Panel
    public RectTransform m_TopItem;                                 //顶部Item
    public RectTransform m_BottomItem;                              //底部Item

    private Vector2 m_PointerStartLocalCursor = Vector2.zero;
    private Vector2 m_ContentStartPosition = Vector2.zero;
    private Bounds m_ContentBounds;
    private Bounds m_ViewBounds;
    private bool m_Dragging;
    private bool m_IsEnable;

    #region Content与ViewPort便捷属性

    /// <summary>
    /// Content的坐标
    /// </summary>
    protected Vector2 ContentPosition
    {
        get { return m_Content.anchoredPosition; }
        set { m_Content.anchoredPosition = value; }
    }

    /// <summary>
    /// Content宽度
    /// </summary>
	protected float ContentWidth
    {
        get { return m_Content.rect.width; }
    }

    /// <summary>
    /// Content高度
    /// </summary>
	protected float ContentHeight
    {
        get { return m_Content.rect.height; }
    }

    /// <summary>
    /// ViewPort宽度
    /// </summary>
	protected float ViewWidth
    {
        get { return m_Viewport.rect.width; }
    }

    /// <summary>
    /// ViewPort高度
    /// </summary>
    protected float ViewHeight
    {
        get { return m_Viewport.rect.height; }
    }

    protected RectTransform viewRect
    {
        get { return m_Viewport; }
    }
    #endregion

    #region 无限循环滚动属性

    private bool _useLoop;                                          //使用Loop功能
    private int _loopIndex;                                         //当前标记位
    private int _loopMaxCount;                                      //循环最大数
    private int _loopCacheCount;                                    //循环缓存数

    private bool _inBack;                                           //是否在back中

    private List<RectTransform> _loopItems;

    /// <summary>
    /// 最后一项高度
    /// </summary>
    private float LastLoopItemHeight
    {
        get { return _loopItems[_loopItems.Count - 1].rect.height; }
    }

    /// <summary>
    /// 第一项高度
    /// </summary>
    private float FirstLoopItemHeight
    {
        get { return _loopItems[0].rect.height; }
    }

    /// <summary>
    /// 顶部Item高度
    /// </summary>
    private float TopItemHeight
    {
        get { return m_TopItem ? m_TopItem.rect.height : 0; }
    }

    /// <summary>
    /// 底部Item高度
    /// </summary>
    private float BottomItemHeight
    {
        get { return m_BottomItem ? m_BottomItem.rect.height : 0; }
    }

    /// <summary>
    /// 最后一项宽度
    /// </summary>
    private float LastLoopItemWidth
    {
        get { return _loopItems[_loopItems.Count - 1].rect.width; }
    }

    /// <summary>
    /// 第一项宽度
    /// </summary>
    private float FirstLoopItemWidth
    {
        get { return _loopItems[0].rect.width; }
    }

    /// <summary>
    /// 最左边Item宽度
    /// </summary>
    private float TopItemWidth
    {
        get { return m_TopItem ? m_TopItem.rect.width : 0; }
    }

    /// <summary>
    /// 最右边Item宽度
    /// </summary>
    private float BottomItemWidth
    {
        get { return m_BottomItem ? m_BottomItem.rect.width : 0; }
    }


    [HideInInspector]
    public UnityAction<int> onLoopFront;
    [HideInInspector]
    public UnityAction<int> onLoopBack;

	[HideInInspector]
	public UnityAction onDragBegin;

	[HideInInspector]
	public UnityAction onPointerDown;

    protected LuaTable _l;
    #endregion

    #region 惯性

    protected Vector2 _lastDistance;                                    //最终距离
    protected Vector2 InertiaDestPointVertical                  //纵向惯性目标点
    {
        get
        {
            Vector2 targetPos = _lastDistance * InertiaStep;
            if (targetPos.y > ViewHeight / 2)
            {
                targetPos.y = ViewHeight / 2;
            }
            if (targetPos.y < -ViewHeight / 2)
            {
                targetPos.y = -ViewHeight / 2;
            }
            return targetPos;
        }
    }
    protected Vector2 InertiaDestPointHorizontal                  //横向惯性目标点
    {
        get
        {
            Vector2 targetPos = _lastDistance * InertiaStep;
            if (targetPos.x > ViewWidth / 2)
            {
                targetPos.x = ViewWidth / 2;
            }
            if (targetPos.x < -ViewWidth / 2)
            {
                targetPos.x = -ViewWidth / 2;
            }
            return targetPos;
        }
    }
    private const float InertiaStep = 5f;                               //惯性距离倍数
    private const float InertiaSpeed = 5f;                              //惯性速度
    private const float OutInertiaSpeed = 30f;                          //出界后
    private float _nowInertiaSpeed;                                     //当前惯性
    private Vector2 _lastPoint = Vector2.zero;                          //最后的点
    private Vector2 _firstPoint = Vector2.zero;                         //最先的点

    private const float ElasticTime = 0.2f;                             //弹性
    private const float MoveTime = 0.3f;                                //移动时间

    #endregion

    #region 释放刷新
    private const float _releaseBorder = 50;
    private const string SwipeUpKey = "common_text_089";            //上拉
    private const string ReleaseKey = "common_text_084";            //放开刷新
    private const string EndOfHistoryKey = "alliance_menber_tips_34";       //["alliance_menber_tips_34"] = "当前无更多",
    public Text m_ReleaseText;                                      //刷新文本
    private bool m_IsRelease;                                       //是否有刷新功能 
    public ReleasePosition m_ReleasePosition;                       //放开刷新功能
    public ReleaseEndShow m_ReleaseEndShow;                         //结束刷新后显示
    [HideInInspector]
    public UnityAction onRelease;
    #endregion


    protected override void Start()
    {
        base.Start();
        Init();
    }

    private void Init()
    {
        if (m_TopItem) m_TopItem.SetAsFirstSibling();
        if (m_BottomItem) m_BottomItem.SetAsLastSibling();
        if (m_ReleasePosition == ReleasePosition.None) return;
        if (m_ReleaseText == null)
        {
            Debuger.LogError("释放刷新找不到Text");
            return;
        }
        m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, SwipeUpKey).ToString();
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        Clean();
		if (onPointerDown != null) {
			onPointerDown.Invoke ();
		}

    }

    public void OnPointerUp(PointerEventData eventData)
    {
        m_Inertia = true;
        m_Dragging = false;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        Clean();
        m_PointerStartLocalCursor = Vector2.zero;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(viewRect, eventData.position, eventData.pressEventCamera, out m_PointerStartLocalCursor);
        m_ContentStartPosition = m_Content.anchoredPosition;
        m_Dragging = true;

		if (onDragBegin != null) {
			onDragBegin.Invoke ();
		}
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        UpdateBounds();
        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;
        TweenBack();
        if (m_Vertical)
        {
            if (max.y < m_ViewBounds.max.y || min.y > m_ViewBounds.min.y)
            {
                _nowInertiaSpeed = OutInertiaSpeed;
            }
            else
            {
                _nowInertiaSpeed = InertiaSpeed;
            }
        }
        if (m_Horizontal)
        {
            if (max.x < m_ViewBounds.max.x || min.x > m_ViewBounds.min.x)
            {
                _nowInertiaSpeed = OutInertiaSpeed;
            }
            else
            {
                _nowInertiaSpeed = InertiaSpeed;
            }
        }
        _lastPoint = Vector2.zero;
        _firstPoint = Vector2.zero;
        m_Inertia = true;
        m_Dragging = false;
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector2 localCursor;
        if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(viewRect, eventData.position, eventData.pressEventCamera, out localCursor))
            return;

        var pointerDelta = localCursor - m_PointerStartLocalCursor;
        Vector2 position = m_ContentStartPosition + pointerDelta;
        _lastDistance = position - ContentPosition;
        MoveDistance(_lastDistance);
    }

    protected virtual void SetContentAnchoredPosition(Vector2 position)
    {
        if (!m_Horizontal)
            position.x = m_Content.anchoredPosition.x;
        if (!m_Vertical)
            position.y = m_Content.anchoredPosition.y;

        if (position != m_Content.anchoredPosition)
        {
            m_Content.anchoredPosition = position;
            UpdateBounds();
        }
    }

    /// <summary>
    /// 移动
    /// </summary>
    /// <param name="delta"></param>
    public bool MoveDistance(Vector2 delta)
    {

        UpdateBounds();
        bool border = false;
        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;
        if (!m_Horizontal)
        {
            delta.x = 0;
        }
        if (!m_Vertical)
        {
            delta.y = 0;
        }
        if (m_Vertical)
        {
            if (max.y + delta.y < m_ViewBounds.max.y - m_clampedLength)
            {
                border = true;
            }
            else if (ViewHeight > ContentHeight)
            {
                if (max.y + delta.y > m_ViewBounds.max.y + m_clampedLength)
                {
                    border = true;
                }
            }
            else if (min.y + delta.y > m_ViewBounds.min.y + m_clampedLength)
            {
                border = true;
            }

            if (m_ReleasePosition != ReleasePosition.None && m_ReleaseText)
            {
                switch (m_ReleasePosition)
                {
                    case ReleasePosition.Down:
                        m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, min.y + delta.y > m_ViewBounds.min.y + _releaseBorder ? ReleaseKey : (!m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.ShowEndHint ? EndOfHistoryKey : SwipeUpKey)).ToString();
                        break;
                }
            }
        }
        if (m_Horizontal)
        {
            if (max.x + delta.x < m_ViewBounds.max.x - m_clampedLength)
            {
                border = true;
            }
            else if (ViewWidth > ContentWidth)
            {
                if (max.x + delta.x > m_ViewBounds.max.x + m_clampedLength)
                {
                    border = true;
                }
            }
            else if (min.x + delta.x > m_ViewBounds.min.x + m_clampedLength)
            {
                border = true;
            }

            if (m_ReleasePosition != ReleasePosition.None && m_ReleaseText)
            {
                switch (m_ReleasePosition)
                {
                    case ReleasePosition.Down:
                        m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, min.x + delta.x > m_ViewBounds.min.x + _releaseBorder ? ReleaseKey : (!m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.ShowEndHint ? EndOfHistoryKey : SwipeUpKey)).ToString();
                        break;
                }
            }
        }
        Vector2 position = ContentPosition + delta;
        delta = CalculateOffset(delta);
        position += delta;
        if (delta.y != 0 && m_Vertical)
            position.y = position.y - RubberDelta(delta.y, m_ViewBounds.size.y);
        if (delta.x != 0 && m_Horizontal)
            position.x = position.x - RubberDelta(delta.x, m_ViewBounds.size.x);
        ContentPosition = position;
        ResetLoopPosition();
        return border;
    }

    private Vector2 CalculateOffset(Vector2 delta)
    {
        Vector2 offset = Vector2.zero;

        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;
        if (m_Vertical)
        {
            min.y += delta.y;
            max.y += delta.y;
            if (max.y < m_ViewBounds.max.y)
                offset.y = m_ViewBounds.max.y - max.y;
            else if (min.y > m_ViewBounds.min.y)
                offset.y = m_ViewBounds.min.y - min.y;
        }
        if (m_Horizontal)
        {
            min.x += delta.x;
            max.x += delta.x;
            if (max.x < m_ViewBounds.max.x)
                offset.x = m_ViewBounds.max.x - max.x;
            else if (min.x > m_ViewBounds.min.x)
                offset.x = m_ViewBounds.min.x - min.x;
        }
        return offset;
    }

    private static float RubberDelta(float overStretching, float viewSize)
    {
        return (1 - (1 / ((Mathf.Abs(overStretching) * 0.55f / viewSize) + 1))) * viewSize * Mathf.Sign(overStretching);
    }

    public LuaTable LuaModule
    {
        get
        {
            if (_l == null)
            {
                _l = LuaHelper.GetLuaComponent(gameObject, "AutoLoopScroll");
            }
            return _l;
        }
    }

    /// <summary>
    /// 初始化循环滚动
    /// </summary>
    /// <param name="loopItems"></param>
    /// <param name="curIndex"></param>
    public void InitLoop(RectTransform[] loopItems, int curIndex)
    {
        _loopIndex = curIndex - 1;
        m_IsRelease = m_ReleasePosition != ReleasePosition.None;
        _loopItems = new List<RectTransform>(loopItems);
        _loopCacheCount = _loopItems.Count;
        for (int i = 0; i < _loopCacheCount; i++)
        {
            _loopItems[i].gameObject.name = "item" + (i + 1);
        }
        if (_loopIndex == 0)
        {
            ContentPosition = Vector2.zero;
        }
    }

    /// <summary>
    /// 重置循环滚动
    /// </summary>
    /// <param name="loopItems"></param>
    public void ResetLoop(RectTransform[] loopItems)
    {
        m_IsRelease = m_ReleasePosition != ReleasePosition.None;
        _loopItems = new List<RectTransform>(loopItems);
        _loopCacheCount = _loopItems.Count;
        for (int i = 0; i < _loopCacheCount; i++)
        {
            _loopItems[i].gameObject.name = "item" + (i + 1);
        }
    }

    /// <summary>
    /// 重置Release
    /// </summary>
    public void ResetReleasePos()
    {
        //无刷新功能
        if (!m_IsRelease && m_ReleaseEndShow != ReleaseEndShow.ShowEndHint) return;
        if (_loopIndex + _loopCacheCount >= _loopMaxCount)
        {
            if (m_ReleaseText)
            {
                m_ReleaseText.gameObject.SetActive(true);
                switch (m_ReleasePosition)
                {
                    case ReleasePosition.None:
                        Debuger.LogError("Scroll设置错误");
                        break;
                    case ReleasePosition.Top:
                        m_ReleaseText.rectTransform.SetAsFirstSibling();
                        break;
                    case ReleasePosition.Down:
                        m_ReleaseText.rectTransform.SetAsLastSibling();
                        break;
                }
            }
        }
        else
        {
            if (m_ReleaseText)
            {
                m_ReleaseText.gameObject.SetActive(false);
            }
        }
    }

    /// <summary>
    /// 设置释放状态
    /// </summary>
    /// <param name="active"></param>
    public void SetReleaseActive(bool active)
    {
        m_IsRelease = active;
        if (m_ReleaseEndShow != ReleaseEndShow.ShowEndHint || active)
        {
            m_ReleaseText.transform.SetAsLastSibling();
            m_ReleaseText.gameObject.SetActive(active);
        }
        else
        {
            m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, !m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.ShowEndHint ? EndOfHistoryKey : SwipeUpKey).ToString();
        }
    }

    /// <summary>
    /// 改变当前标记位
    /// </summary>
    /// <param name="addCount"></param>
    public void AddCurrentIndex(int addCount)
    {
        _loopIndex = _loopIndex + addCount;
    }

    /// <summary>
    /// 设置循环滚动最大数值
    /// </summary>
    /// <param name="loopMax"></param>
    public void SetLoopMax(int loopMax)
    {
        _loopMaxCount = loopMax;
        _useLoop = _loopItems.Count < loopMax;
        //如果有释放刷新的功能
        ResetReleasePos();
    }

    /// <summary>
    /// 获取循环滚动最大数值
    /// </summary>
    /// <param name="loopMax"></param>
    public int GetLoopMax(GameObject go)
    {
        int maxCount = 0;
        if (go)
        {
            RectTransform tran = go.GetComponent<RectTransform>();
            if (tran)
                maxCount = Mathf.CeilToInt(m_Viewport.rect.height / tran.rect.height);
        }
        return maxCount;
    }

    /// <summary>
    /// 检测当前状态是否达到需要重置Item项
    /// </summary>
    public void ResetLoopPosition()
    {
        if (!_useLoop) return;
        UpdateBounds();
        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;
        if (m_Vertical)
        {
            if (_loopIndex + _loopCacheCount < _loopMaxCount && m_ViewBounds.min.y - min.y < LastLoopItemHeight + BottomItemHeight && max.y - m_ViewBounds.max.y > FirstLoopItemHeight)
            {
                VerticalUp();
                _loopIndex++;
                if (onLoopFront != null && m_IsEnable)
                {
                    onLoopFront.Invoke(_loopIndex + _loopCacheCount);
                }
                ResetReleasePos();
            }
            else if (_loopIndex > 0 && max.y - m_ViewBounds.max.y < FirstLoopItemHeight + TopItemHeight)
            {
                VerticalDown();
                if (onLoopBack != null && m_IsEnable)
                {
                    onLoopBack.Invoke(_loopIndex);
                }
                _loopIndex--;
                ResetReleasePos();
            }
            if (m_HeadPanel)
            {
                Vector2 offset = new Vector2(0, m_HeadPanel.rect.height);
                if (_loopIndex > 0)
                {
                    m_HeadPanel.gameObject.SetActive(false);
                    ContentPosition = ContentPosition - offset;
                    m_ContentStartPosition = m_ContentStartPosition - offset;
                }
                else
                {
                    m_HeadPanel.gameObject.SetActive(true);
                    m_HeadPanel.SetAsFirstSibling();
                    ContentPosition = ContentPosition + offset;
                    m_ContentStartPosition = m_ContentStartPosition + offset;
                }
            }
        }
        if (m_Horizontal)
        {
            if (_loopIndex + _loopCacheCount < _loopMaxCount && m_ViewBounds.min.x - min.x > LastLoopItemWidth + BottomItemWidth && max.x - m_ViewBounds.max.x < FirstLoopItemWidth)
            {
                HorizontalLeft(); 
                _loopIndex++;
                if (onLoopFront != null && m_IsEnable)
                {
                    onLoopFront.Invoke(_loopIndex + _loopCacheCount);
                }
                ResetReleasePos();
            }
            else if (_loopIndex > 0 && max.x - m_ViewBounds.max.x > FirstLoopItemWidth + TopItemWidth)
            {
                HorizontalRight();
                if (onLoopBack != null && m_IsEnable)
                {
                    onLoopBack.Invoke(_loopIndex);
                }
                _loopIndex--;
                ResetReleasePos();
            }
            if (m_HeadPanel)
            {
                Vector2 offset = new Vector2(m_HeadPanel.rect.width, 0);
                if (_loopIndex > 0)
                {
                    m_HeadPanel.gameObject.SetActive(false);
                    ContentPosition = ContentPosition - offset;
                    m_ContentStartPosition = m_ContentStartPosition - offset;
                }
                else
                {
                    m_HeadPanel.gameObject.SetActive(true);
                    m_HeadPanel.SetAsFirstSibling();
                    ContentPosition = ContentPosition + offset;
                    m_ContentStartPosition = m_ContentStartPosition + offset;
                }
            }
        }
    }

    /// <summary>
    /// 向上拖拽(Item下移)
    /// </summary>
    protected virtual void VerticalUp()
    {
        RectTransform rt = _loopItems[0];
        if (m_BottomItem)
            rt.SetSiblingIndex(m_Content.childCount - 2);
        else
            rt.SetAsLastSibling();
        _loopItems.RemoveAt(0);
        _loopItems.Add(rt);
        Vector2 offset = new Vector2(0, rt.rect.height);
        ContentPosition = ContentPosition - offset;
        m_ContentStartPosition = m_ContentStartPosition - offset;
    }

    /// <summary>
    /// 向下拖拽(Item上移)
    /// </summary>
    protected virtual void VerticalDown()
    {
        int lastIndex = _loopItems.Count - 1;
        RectTransform rt = _loopItems[lastIndex];
        if (m_TopItem)
            rt.SetSiblingIndex(1);
        else
            rt.SetAsFirstSibling();
        _loopItems.RemoveAt(lastIndex);
        _loopItems.Insert(0, rt);
        Vector2 offset = new Vector2(0, rt.rect.height);
        ContentPosition = ContentPosition + offset;
        m_ContentStartPosition = m_ContentStartPosition + offset;
    }

    /// <summary>
    /// 向左拖拽(Item右移)
    /// </summary>
    protected virtual void HorizontalLeft()
    {
        RectTransform rt = _loopItems[0];
        if (m_BottomItem)
            rt.SetSiblingIndex(m_Content.childCount - 2);
        else
            rt.SetAsLastSibling();
        _loopItems.RemoveAt(0);
        _loopItems.Add(rt);
        Vector2 offset = new Vector2(rt.rect.width, 0);
        ContentPosition = ContentPosition - offset;
        m_ContentStartPosition = m_ContentStartPosition - offset;
    }

    /// <summary>
    /// 向右拖拽(Item左移)
    /// </summary>
    protected virtual void HorizontalRight()
    {
        int lastIndex = _loopItems.Count - 1;
        RectTransform rt = _loopItems[lastIndex];
        if (m_TopItem)
            rt.SetSiblingIndex(1);
        else
            rt.SetAsFirstSibling();
        _loopItems.RemoveAt(lastIndex);
        _loopItems.Insert(0, rt);
        Vector2 offset = new Vector2(rt.rect.width, 0);
        ContentPosition = ContentPosition + offset;
        m_ContentStartPosition = m_ContentStartPosition + offset;
    }

    private void UpdateBounds()
    {
        m_ViewBounds = new Bounds(viewRect.rect.center, viewRect.rect.size);
        m_ContentBounds = GetBounds();

        if (m_Content == null)
            return;

        Vector3 contentSize = m_ContentBounds.size;
        Vector3 contentPos = m_ContentBounds.center;
        Vector3 excess = m_ViewBounds.size - contentSize;
        if (excess.x > 0)
        {
            contentPos.x -= excess.x * (m_Content.pivot.x - 0.5f);
            contentSize.x = m_ViewBounds.size.x;
        }
        if (excess.y > 0)
        {
            contentPos.y -= excess.y * (m_Content.pivot.y - 0.5f);
            contentSize.y = m_ViewBounds.size.y;
        }

        m_ContentBounds.size = contentSize;
        m_ContentBounds.center = contentPos;
    }

    private readonly Vector3[] m_Corners = new Vector3[4];
    private Bounds GetBounds()
    {
        if (m_Content == null)
            return new Bounds();

        var vMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
        var vMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);

        var toLocal = viewRect.worldToLocalMatrix;
        m_Content.GetWorldCorners(m_Corners);
        for (int j = 0; j < 4; j++)
        {
            Vector3 v = toLocal.MultiplyPoint3x4(m_Corners[j]);
            vMin = Vector3.Min(v, vMin);
            vMax = Vector3.Max(v, vMax);
        }

        var bounds = new Bounds(vMin, Vector3.zero);
        bounds.Encapsulate(vMax);
        return bounds;
    }

    protected LTDescr _ltDescrVertical;                   //垂直归位动画.
    protected LTDescr _ltDescrHorizontal;                   //水平归位动画.
    /// <summary>
    /// 归位动画
    /// </summary>
    public void TweenBack(bool b_refresh = true)
    {
        _inBack = true;
        Clean();
        UpdateBounds();
        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;

        if (m_Vertical)
        {
            if (max.y < m_ViewBounds.max.y)
            {
                float distance = m_ViewBounds.max.y - max.y + ContentPosition.y;
                _ltDescrVertical = LeanTween.moveY(m_Content, distance, ElasticTime);
            }
            else if (ViewHeight > ContentHeight)
            {
                if (max.y > m_ViewBounds.max.y)
                {
                    float distance = m_ViewBounds.max.y - max.y + ContentPosition.y;
                    _ltDescrVertical = LeanTween.moveY(m_Content, distance, ElasticTime);
                }
                else
                {
                    _inBack = false;
                    return;
                }
            }
            else if (min.y > m_ViewBounds.min.y)
            {
                float distance = m_ViewBounds.min.y - min.y + ContentPosition.y;
                _ltDescrVertical = LeanTween.moveY(m_Content, distance, ElasticTime);
            }
            else
            {
                if (b_refresh)
                {
                    m_Inertia = true;
                }
                _inBack = false;
                return;
            }
            if (!b_refresh) return;
            bool needRefrush = CheckRefrush();
            if (needRefrush)
            {
                m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, !m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.ShowEndHint ? EndOfHistoryKey : SwipeUpKey).ToString();
                if (m_IsRelease)
                {
                    _ltDescrVertical.setOnComplete(delegate ()
                    {
                        if (onRelease != null)
                        {
                            onRelease.Invoke();
                            _inBack = false;
                        }
                    });
                }
            }
        }
        if (m_Horizontal)
        {
            if (max.x < m_ViewBounds.max.x)
            {
                float distance = m_ViewBounds.max.x - max.x + ContentPosition.x;
                _ltDescrHorizontal = LeanTween.moveX(m_Content, distance, ElasticTime);
            }
            else if (ViewWidth > ContentWidth)
            {
                if (max.x > m_ViewBounds.max.x)
                {
                    float distance = m_ViewBounds.max.x - max.x + ContentPosition.x;
                    _ltDescrHorizontal = LeanTween.moveX(m_Content, distance, ElasticTime);
                }
                else
                {
                    _inBack = false;
                    return;
                }
            }
            else if (min.x > m_ViewBounds.min.x)
            {
                float distance = m_ViewBounds.min.x - min.x + ContentPosition.x;
                _ltDescrHorizontal = LeanTween.moveX(m_Content, distance, ElasticTime);
            }
            else
            {
                if (b_refresh)
                {
                    m_Inertia = true;
                }
                _inBack = false;
                return;
            }
            if (!b_refresh) return;
            bool needRefrush = CheckRefrush();
            if (needRefrush)
            {
                m_ReleaseText.text = LuaManager.Instance.CallFunc(LuaEventDefine.GET_LANG, !m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.ShowEndHint ? EndOfHistoryKey : SwipeUpKey).ToString();
                if (m_IsRelease)
                {
                    _ltDescrHorizontal.setOnComplete(delegate ()
                    {
                        if (onRelease != null)
                        {
                            onRelease.Invoke();
                            _inBack = false;
                        }
                    });
                }
            }
        }
    }

    /// <summary>
    /// 检测是否可以刷新
    /// </summary>
    /// <returns></returns>
    public bool CheckRefrush()
    {
        if (!m_IsRelease && m_ReleaseEndShow == ReleaseEndShow.Hide) return false;
        UpdateBounds();
        Vector2 min = m_ContentBounds.min;
        Vector2 max = m_ContentBounds.max;
        switch (m_ReleasePosition)
        {
            case ReleasePosition.Down:
                if (m_Vertical && min.y > m_ViewBounds.min.y + _releaseBorder)
                {
                    return true;
                }
                if (m_Horizontal && min.x > m_ViewBounds.min.x + _releaseBorder)
                {
                    return true;
                }
                break;
        }
        return false;
    }


    private bool m_Inertia = false;

    void LateUpdate()
    {
        if (!m_IsEnable || m_Dragging) return;
        if (m_Inertia)
        {
            if (_nowInertiaSpeed==OutInertiaSpeed)
            {
                TweenBack();
                m_Inertia = false;
                return;
            }
            Vector2 _inertiaDestPoint = m_Vertical ? InertiaDestPointVertical : (m_Horizontal ? InertiaDestPointHorizontal : Vector2.zero);
            _firstPoint = Vector2.Lerp(_firstPoint, _inertiaDestPoint, _nowInertiaSpeed * Time.deltaTime);
            Vector2 moveOffset = _firstPoint - _lastPoint;
            bool border = MoveDistance(moveOffset);
            _lastPoint = _firstPoint;
            if ((_firstPoint - _inertiaDestPoint).magnitude < 1 || border)
            {
                TweenBack();
                m_Inertia = false;
            }
        }
        else
        {
            if (!_inBack)
            {
                TweenBack(false);
            }
        }
    }

    protected override void OnEnable()
    {
        base.OnEnable();
        m_IsEnable = true;
        CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
    }

    protected override void OnDisable()
    {
        CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(this);
        m_IsEnable = false;
        m_Inertia = false;
        LayoutRebuilder.MarkLayoutForRebuild(transform.rectTransform());
        base.OnDisable();
    }

    protected override void OnCanvasHierarchyChanged()
    {
        base.OnCanvasHierarchyChanged();
        bool isShow = CheckIsShow();
        if (isShow)
        {
            m_IsEnable = true;
        }
        else
        {
            m_IsEnable = false;
            m_Inertia = false;
        }
    }

    public void Rebuild(CanvasUpdate executing)
    { }

    public void LayoutComplete()
    { }

    public void GraphicUpdateComplete()
    { }

    /// <summary>
    /// 清理(动画与惯性)
    /// </summary>
	protected void Clean()
    {
        m_Inertia = false;
        if (_ltDescrVertical != null)
        {
            _ltDescrVertical.LTRemove();
            _ltDescrVertical = null;
        }
        if (_ltDescrHorizontal != null)
        {
            _ltDescrHorizontal.LTRemove();
            _ltDescrHorizontal = null;
        }
    }
}
